#include <iostream>
#include <fstream>
#include <string>

#include <unistd.h>
#include <errno.h>
#include <vector>

#include "XBaseClient.h"
#include "XBaseCommand.h"

#ifdef LOGGER
#	include <log4cplus/logger.h>
#	include <log4cplus/configurator.h>
#	include <log4cplus/tstring.h>
#endif

using namespace std;

string gTableName;
string gMasterIP;
int gMasterPort = 20081;

static size_t split(std::vector<std::string>& result, const std::string & str, const char sp)
{
	size_t startPos = 0;
	size_t endPos = 0;
	while ( (endPos = str.find( sp, startPos )) != std::string::npos ) {
		if ( (endPos - startPos) > 0 ) {
			result.push_back( str.substr( startPos, (endPos - startPos) ) );
		}

		startPos = endPos + 1;
	}
	if ( !str.empty() && startPos <= (str.length () - 1) ) {
		result.push_back( str.substr (startPos) );
	}

	return result.size();
}

struct SDServerRes
{
	std::string contentID;
	std::string fileSize;
	std::string fullContentID;
	std::string fileUrl;
	std::string fileUrlNoUP;
	std::string pageUrl;
	std::string urlQuality;
	std::string lastValidTime;
	std::string firstInvalidTime;
	std::string invalidTimes;

	friend std::ifstream& operator>> ( std::ifstream& in, SDServerRes& serverRes );
	friend std::ostream& operator<< ( std::ostream& out, const SDServerRes& serverRes );
};

std::ifstream& operator>> ( std::ifstream& in, SDServerRes& serverRes )
{
	#if 0
	in >> serverRes.contentID >> serverRes.fileSize >> serverRes.fullContentID
		>> serverRes.fileUrl >> serverRes.fileUrlNoUP >> serverRes.pageUrl
		>> serverRes.urlQuality >> serverRes.lastValidTime >> serverRes.firstInvalidTime
		>> serverRes.invalidTimes;
	#else
	std::string line;
	if ( !( (std::getline( in, line )).fail() ) ) {
		std::vector<std::string> columns;
		size_t columnCount = split( columns, line, '\t' );
		if ( columnCount != 10 ) {
			std::cout << "columnCount ne 10" << std::endl;
		} else {
			int idx = 0;
			serverRes.contentID = columns[idx++];
			serverRes.fileSize = columns[idx++];
			serverRes.fullContentID = columns[idx++];
			serverRes.fileUrl = columns[idx++];
			serverRes.fileUrlNoUP = columns[idx++];
			serverRes.pageUrl = columns[idx++];
			serverRes.urlQuality = columns[idx++];
			serverRes.lastValidTime = columns[idx++];
			serverRes.firstInvalidTime = columns[idx++];
			serverRes.invalidTimes = columns[idx++];
		}
	}
	#endif

	return in;
}

std::ostream& operator<< ( std::ostream& out, const SDServerRes& serverRes )
{
	out << "contentID" << "\t" << serverRes.contentID << "\n"
		<< "fileSize" << "\t" << serverRes.fileSize << "\n"
		<< "fullContentID" << "\t" << serverRes.fullContentID << "\n"
		<< "fileUrl" << "\t" << serverRes.fileUrl << "\n"
		<< "fileUrlNoUP" << "\t" << serverRes.fileUrlNoUP << "\n"
		<< "pageUrl" << "\t" << serverRes.pageUrl << "\n"
		<< "urlQuality" << "\t" << serverRes.urlQuality << "\n"
		<< "lastValidTime" << "\t" << serverRes.lastValidTime << "\n"
		<< "firstInvalidTime" << "\t" << serverRes.firstInvalidTime << "\n"
		<< "invalidTimes" << "\t" << serverRes.invalidTimes;

	return out;
}

void test_insert(const std::string& data_filename)
{
	XBaseClient cn( gMasterIP.c_str(), gMasterPort );
	cn.set_recv_timeout( 3600*1000 );
	cn.set_send_timeout( 3600*1000 );

	std::ifstream in( data_filename.c_str() );
	if ( in.fail() ) {
		std::cerr << "open " << data_filename << " fail. errno " << errno << std::endl;
		return;
	}

	const int BUFSIZE = 1024;
	char buffer[ BUFSIZE ];	

	int row = 1;
	SDServerRes serverRes;
	while ( !( in >> serverRes ).fail() ) {

		std::cout << "*************************** " << (row++) << ". row ***************************" << std::endl;
		std::cout << serverRes << std::endl;

		XBaseCommandInsert cmd;
		cmd.set_table_name( gTableName );

		//serverRes.contentID = Utility::hex_2_str( serverRes.contentID );
		//serverRes.fullContentID = Utility::hex_2_str( serverRes.fullContentID );

		snprintf( buffer, sizeof(buffer), "fileUrlNoUP:%s", serverRes.fileUrlNoUP.c_str() );
		cmd.add( serverRes.fileUrlNoUP, serverRes.contentID, buffer );
		snprintf( buffer, sizeof(buffer), "fileSize:%s", serverRes.fileUrlNoUP.c_str() );
		cmd.add( serverRes.fileSize, serverRes.contentID, buffer );
		snprintf( buffer, sizeof(buffer), "fullContentID:%s", serverRes.fileUrlNoUP.c_str() );
		cmd.add( serverRes.fullContentID, serverRes.contentID, buffer );
		snprintf( buffer, sizeof(buffer), "fileUrl:%s", serverRes.fileUrlNoUP.c_str() );
		cmd.add( serverRes.fileUrl, serverRes.contentID, buffer );
		snprintf( buffer, sizeof(buffer), "pageUrl:%s", serverRes.fileUrlNoUP.c_str() );
		cmd.add( serverRes.pageUrl, serverRes.contentID, buffer );
		snprintf( buffer, sizeof(buffer), "urlQuality:%s", serverRes.fileUrlNoUP.c_str() );
		cmd.add( serverRes.urlQuality, serverRes.contentID, buffer );
		snprintf( buffer, sizeof(buffer), "lastValidTime:%s", serverRes.fileUrlNoUP.c_str() );
		cmd.add( serverRes.lastValidTime, serverRes.contentID, buffer );
		snprintf( buffer, sizeof(buffer), "firstInvalidTime:%s", serverRes.fileUrlNoUP.c_str() );
		cmd.add( serverRes.firstInvalidTime, serverRes.contentID, buffer );
		snprintf( buffer, sizeof(buffer), "invalidTimes:%s", serverRes.fileUrlNoUP.c_str() );
		cmd.add( serverRes.invalidTimes, serverRes.contentID, buffer );

		//continue;

		cn.execute( &cmd );		
		if ( cmd.fail() ) {
			std::cout << cmd.errorstr() << std::endl;
		}
		else {
			std::cout << std::endl << "Query OK, " << cmd.affected_rows() << " rows affected" << std::endl;
		}

		//std::cout << cmd.to_string() << std::endl;
	}	
}

int main(int argc, char* argv[])
{	
	#ifdef LOGGER
	log4cplus::PropertyConfigurator::doConfigure("../conf/log4cplus.properties");
	#endif

	string filename;

	extern char *optarg;
	extern int optopt;

	char c;
	 while ( (c = getopt( argc, argv, ":h:p:t:f:" ) ) != -1 ) {
	 	switch( c ) {
			case 'h':
				gMasterIP = optarg; 
				break;
			case 'p':
				gMasterPort = atoi ( optarg );
				break;
			case 't':
				gTableName = optarg;
				break;
			case 'f':
				filename = optarg;
				break;
			case ':':       /* without operand */
				fprintf(stderr, "Option -%c requires an operand\n", optopt);    
				exit( EXIT_FAILURE );
				break;
			case '?':
				fprintf(stderr, "Unrecognized option: -%c\n", optopt);
				exit( EXIT_FAILURE );
				break;
		}
	}

	 if ( gMasterIP.empty() || gTableName.empty() ) {
	 	cerr << "Usage: " << argv[0] << " -h 192.168.3.217 -p 20081 -t sd_server_res -f sd_server_res_0.data" << endl;
	 	exit( EXIT_FAILURE );
	 }
	
	test_insert( filename );
}

